/* 
 * $Id$
 *
 * UMKC Robotics 2009
 *
 * This file holds the user interface definition for all io 
 * on the robot.
 *
 *
**/

#ifndef IOPUBLIC_H
#define IOPUBLIC_H

#include <stdarg.h>
#include "iobase.h"

/* Definition for the BotDeviceIdx.  This enum serves
 * as in index into an array that holds information about
 * all devices on the robot.  You pass the index value
 * to one of the control functions or to readf()/writef().
 * (see below.)  
 *
 * There is a special case of 'Balldev'.  The command/read/write
 * will be issued to all known devices for which a driver
 * has been implemented. */
typedef enum io_idx { 

  Balldev,
  Bstdin,
  Bstdout,
  Bstderr,
  LCD
 /*
 * ,USART0
 * ,USART1
 * ... etc...
 */

} BotDeviceIdx;



/* Definition for the io controller.  This is the object
 * that allows you to readf() and writef() arbitrary
 * chunks of data from/to any device that has a driver
 * implemented.
 *
 * IO assumes some reasonable stdio module within libc.
 * Specifically, all io is built around vfscanf() (for
 * reads) and vfprintf() (for writes).
 *
 * These functions are central to C standard io and you
 * can find documentation at:
 *
 * 	shell$> man 3 printf
 *
 * or, google.
 *
 * This api provides bprintf(), bfprintf(), eprintf(),
 * bscanf() and bfscanf() as macros that call the io
 * controller's writef() or readf() function.  
 *
 * IO devices cannot be created dynamically without
 * usnig malloc().  We don't want (or need) to do that
 * as it would inject gobs of unnecessary code.
 *
 * The BotIo object allows us to install all devices on
 * demand (likely very early on in any program).  The
 * BotIoctl object allows us to work with any particular
 * device.
 *
 * All devices are stored in an array of BotIoctl structs.
 * Therefore, the BotDeviceIdx is our key to executing
 * a particular function for a given device.
 **/ 


typedef struct bot_io {

  int (*init)();
  int (*reset)();

} BotIo;


typedef struct bot_ioctl {

  int (*load)(BotDeviceIdx);
  int (*reset)(BotDeviceIdx);
  int (*unload)(BotDeviceIdx);
  int (*clone)(BotDeviceIdx, BotDeviceIdx);
  int (*readf)(BotDeviceIdx, const char*, ...); 
  int (*writef)(BotDeviceIdx, const char*, ...);    

} BotIoctl;


/* here are the common printf()/scanf() derivatives.  If you
 * write a device driver - you could implment similar defines.
 * ex:  lcdprintf(), usart0printf(), etc....  Better yet, 
 * just use bfprintf(). 
 *
 * These are provided as a convenience - so you don't have to
 * write:  `bioctl.writef(Bstdout, "blahblah\n")' and can
 * instead just type bprintf() like you would with stdio.
 *
 * The const bioctl object is initialized in iopublic.c.  To
 * use it you have to a) link against iopublic.o and b) declare
 * it:
 * 	extern const BotIoctl bioctl;
 *
 * in your file.
 *
 * See the main.c file.  You *must* do this or the defines
 * below won't work.
 **/
#define bprintf(fmt, ...) \
	bioctl.writef(Bstdout, fmt, ##__VA_ARGS__)

#define bfprintf(dev_idx, fmt, ...) \
	bioctl.writef(dev_idx, fmt, ##__VA_ARGS__)

#define bscanf(fmt, ...) \
    	bioctl.readf(Bstdin, fmt, ##__VA_ARGS__)

#define bfscanf(dev_idx, fmt, ...) \
    	bioctl.readf(dev_idx, fmt, ##__VA_ARGS__)

#endif
